<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>
		<div id="">
			https://www.cnblogs.com/spongeCoder/p/17551652.html
			<br />js判断数据类型的四种方式
			<br />1.typeof
			<br />用法：typeof '123' === 'string'
			<br />缺点：只能判断基础数据类型（除null以外），如果是引用数据类型（如数组、函数、对象等）会返回Object
			<br />因为typeof是直接在计算机里面基于二进制值进行检测的，也就是数据类型都是二进制值，对象存储在计算机中，二进制的值都是以000开头，而null值为000，所以typeof(null)为object
			<br /><br />

			<br />2.instanceof
			<br />用法：'123' instanceof String
			<br />缺点：无法检测基础数据类型，因为instanceof是检测当前判断的类是否出现在实例的原型对象，会循着原型链寻找，所以我们可以改变原型链的指向导致数据类型不准确；
			<br /><br />

			<br />3.constructor
			<br />用法：'123'.constructor === String
			<br />缺点：constructor可以改变，会导致判断不准确；
			<br /><br />

			<br />4.Object.prototype.toString.call()
			<br />用法：Object.prototype.toString.call('123')；
			<br />缺点：写起来比较麻烦；
			<br /><br />

			<br />此方法是检测数据类型最准确的方法
			<br />总结
			<br />① typeof只能检测基本数据类型（除null），对于数组、对象、正则等引用数据类型都返回为Object；
			<br />② instanceof不能检测基本数据类型，检测引用类型时会顺着原型链往上找，只要原型链上存在就会返回true，我们也可以随意更改原型链的指向，导致检测结果不准确；
			<br />③ constructor可以检测基本数据类型，也能分辨出数组和对象，因为我们可以更改constructor，随意会导致检测结果不准确；
			<br />④ Object.prototype.toString.call()是最准确的；
			<br /><br />

			<br />jQuery提供了一系列工具方法，用来判断数据类型，以弥补JavaScript原生的typeof运算符的不足。以下方法对参数进行判断，返回一个布尔值。
			<br />jQuery.isArray();是否为数组
			<br />jQuery.isEmptyObject();是否为空对象 （不含可枚举属性）。
			<br />jQuery.isFunction():是否为函数
			<br />jQuery.isNumberic():是否为数字
			<br />jQuery.isPlainObject():是否为使用“{}”或“new Object”生成对象，而不是浏览器原生提供的对象。
			<br />jQuery.isWindow(): 是否为window对象；
			<br />jQuery.isXMLDoc(): 判断一个DOM节点是否处于XML文档中。
		</div>
		<script type="text/javascript">
			// https://www.cnblogs.com/libo-web/p/15754432.html
			{
				// typeof
				console.log('数据类型判断 -  typeof');
				console.log(typeof ""); // string
				console.log(typeof 1); // number
				console.log(typeof true); // boolean
				console.log(typeof undefined); // undefined
				console.log(typeof null); // object
				console.log(typeof []); // object
				console.log(typeof {}); // object
				console.log(typeof function() {}); // function
				console.log(typeof console.log); // function
				console.log(typeof Symbol()); // symbol
				console.log(typeof 23423n); // bigint
			}

			{
				// instanceof
				console.log('数据类型判断 -  instanceof');
				function my_instanceof(L, R) {
					const O = R.prototype;
					if (L === null) {
						return false;
					}
					L = L.__proto__;
					while (true) {
						if (L === null) {
							return false;
						}
						if (L === O) {
							return true;
						}
						L = L.__proto__;
					}
				}
				function A(name, age) {
					this.name = name;
					this.age = age;
				}
				a = new A('张三', 18);
				console.log(a instanceof A) // true
				obj = new Object()
				// obj = {}
				console.log(obj instanceof Object); // true
				arr = new Array()
				// arr = []
				console.log(arr instanceof Array); // true
				date = new Date()
				console.log(date instanceof Date); // true
				// 注意：instanceof后面一定要是对象类型，instanceof前面相当于它的实例对象,
				// 后面的对象类型大小写不能写错，该方法试用一些条件选择或分支
				console.log('libo' instanceof String); // false  
				console.log(NaN instanceof Number); // false
				console.log(9 instanceof Number); // false
				console.log(true instanceof Boolean); // false 
				console.log(null instanceof Object); // false
				console.log(Array.isArray([])); // true
				console.log([] instanceof Array); // true
				console.log({} instanceof Object); // true
				console.log(function() {} instanceof Function); // true
				
				const o = {
					number: 18,
					arr: [],
					obj: {}
				}
				Object.values(o).forEach((val, key) => {
					if (val instanceof Array) {
						console.log('Array')
					} else if (val instanceof Object) {
						console.log('Object')
					} else {
						console.log('null')
					}
				})
			}

			{
				// Object.prototype.toString.call
				console.log('数据类型判断 -  Object.prototype.toString.call');
				console.log(Object.prototype.toString.call(undefined)); // [object Undefined]
				console.log(Object.prototype.toString.call(null)); // [object Null]
				console.log(Object.prototype.toString.call('')); // [object String]
				console.log(Object.prototype.toString.call(1)); // [object Number]
				console.log(Object.prototype.toString.call(true)); // [object Boolean]
				console.log(Object.prototype.toString.call([])); // [object Array]
				console.log(Object.prototype.toString.call({})); // [object Object]
				console.log(Object.prototype.toString.call(new Function())); // [object Function]
				console.log(Object.prototype.toString.call(new Date())); // [object Date]
				console.log(Object.prototype.toString.call(Symbol())); // [object Symbol]
				console.log(Object.prototype.toString.call(new RegExp())); // [object RegExp]
				console.log(Object.prototype.toString.call(new Error())); // [object Error]
				console.log(Object.prototype.toString.call(document)); // [object HTMLDocument]
				console.log(Object.prototype.toString.call(window)); // [object Window]
			}
			
			{
				// constructor
				console.log('数据类型判断 -  constructor');
				let udf = undefined;
				let nul = null;
				let str = "biu~";
				let num = 23;
				let bool = true;
				let array = [1, 2, 3];
				let date = new Date();
				let reg = new RegExp();
				let fn = function() {
					console.log(886);
				};
				console.log(str.constructor); // String
				console.log(num.constructor); // Number
				console.log(bool.constructor); // Boolean
				console.log(date.constructor); // Date
				console.log(array.constructor); // Array
				console.log(fn.constructor); // Function
				console.log(reg.constructor); // RegExp
			}
		</script>
	</body>
</html>